﻿using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Microsoft.VisualBasic.FileIO;


namespace SymbolicLinkManageCore
{
    public enum PathType { FileType = 0x0, DirectoryType = 0x1, NotExistType }
    public enum RelativeDirectoryType { CurrentEnvironment, IODirectoryCurrentDirectory, CurrentProcessMainModule, CurrentDomainBase, ApplicationBase }
    [Serializable]
    public class LinkTypeException : Exception
    {
        public LinkTypeException() { }
        public LinkTypeException(string message) : base(message) { }
        public LinkTypeException(string message, Exception inner) : base(message, inner) { }
        [Obsolete]
        protected LinkTypeException(
          System.Runtime.Serialization.SerializationInfo info,
          System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
    }


    public class PathInfo : FileSystemInfo
    {


        //-------------------------------------------------------------
        public override bool Exists => Path.Exists(FullPath);

        private string m_Name;
        public override string Name => m_Name;
        public PathType PathType => GetPathType(FullPath);

        public DirectoryInfo? Parent
        {
            get
            {
                string? directoryName = Path.GetDirectoryName(Path.IsPathRooted(FullPath) ? FullPath : Path.TrimEndingDirectorySeparator(FullPath));
                if (directoryName == null)
                {
                    return null;
                }
                return new DirectoryInfo(directoryName);
            }
        }
        public string ParentDirectoryPath
        {
            get
            {
                string? directoryName = Path.GetDirectoryName(Path.IsPathRooted(FullPath) ? FullPath : Path.TrimEndingDirectorySeparator(FullPath));
                if (directoryName == null)
                {
                    return string.Empty;
                }
                return directoryName;
            }
        }
        public DriveInfo? driveInfo
        {
            get
            {
                if (string.IsNullOrWhiteSpace(FullPath))
                    return null;
                string? root = Path.GetPathRoot(FullPath);
                if (string.IsNullOrEmpty(root))
                    return null;
                return new DriveInfo(root);
            }
        }

        public FileInfo? FileInfo => PathType == PathType.DirectoryType ? null : new FileInfo(FullName);
        public DirectoryInfo? DirectoryInfo => PathType == PathType.FileType ? null : new DirectoryInfo(FullName);
        public void DeleteToRecycleBin()
        {
            PathType m_PathType = GetPathType(FullPath);
            if (m_PathType == PathType.DirectoryType)
                FileSystem.DeleteDirectory(FullPath, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin);
            else if (m_PathType == PathType.FileType)
                FileSystem.DeleteFile(FullPath, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin);
        }
        public override void Delete()
        {
            PathType m_PathType = GetPathType(FullPath);
            if (m_PathType == PathType.DirectoryType)
                Directory.Delete(FullPath);
            else if (m_PathType == PathType.FileType)
                File.Delete(FullPath);
        }
        public void Delete(bool recursive)
        {
            PathType m_PathType = GetPathType(FullPath);
            if (m_PathType == PathType.DirectoryType)
                Directory.Delete(FullPath, recursive);
            else if (m_PathType == PathType.FileType)
                File.Delete(FullPath);
        }



        public PathInfo(string Path)
        {
            OriginalPath = Path.TrimEnd('/', '\\');
            FullPath = System.IO.Path.IsPathRooted(Path) ? Path : System.IO.Path.GetFullPath(Path);
            FullPath = FullPath.TrimEnd('/', '\\');
            m_Name = FullPath?.Split('/', '\\').LastOrDefault() ?? string.Empty;
        }
        public PathInfo(string Path, string BaseDirectory)
        {
            OriginalPath = Path.TrimEnd('/', '\\');
            FullPath = System.IO.Path.IsPathRooted(Path) ? Path : System.IO.Path.GetFullPath(Path, BaseDirectory);
            FullPath = FullPath.TrimEnd('/', '\\');
            m_Name = FullPath?.Split('/', '\\').LastOrDefault() ?? string.Empty;
        }
        public PathInfo(string Path, RelativeDirectoryType relativeDirectoryType)
        {
            OriginalPath = Path.TrimEnd('/', '\\');
            FullPath = System.IO.Path.IsPathRooted(Path) ? Path : relativeDirectoryType switch
            {
                RelativeDirectoryType.CurrentEnvironment => System.IO.Path.GetFullPath(Path, Environment.CurrentDirectory),
                RelativeDirectoryType.IODirectoryCurrentDirectory => System.IO.Path.GetFullPath(Path, Directory.GetCurrentDirectory()),
                RelativeDirectoryType.CurrentProcessMainModule => System.IO.Path.GetFullPath(Path, System.IO.Path.GetDirectoryName(Process.GetCurrentProcess()?.MainModule?.FileName) ?? AppDomain.CurrentDomain.BaseDirectory),
                RelativeDirectoryType.CurrentDomainBase => System.IO.Path.GetFullPath(Path, AppDomain.CurrentDomain.BaseDirectory),
                RelativeDirectoryType.ApplicationBase => System.IO.Path.GetFullPath(Path, AppDomain.CurrentDomain.SetupInformation.ApplicationBase ?? AppDomain.CurrentDomain.BaseDirectory),
                _ => System.IO.Path.GetFullPath(Path, Directory.GetCurrentDirectory())
            };

            FullPath = FullPath.TrimEnd('/', '\\');
            m_Name = FullPath?.Split('/', '\\').LastOrDefault() ?? string.Empty;
        }


        public static PathType GetPathType(string? FullPath) => Path.Exists(FullPath) ? (File.GetAttributes(FullPath) & FileAttributes.Directory) > 0 ? PathType.DirectoryType : PathType.FileType : PathType.NotExistType;

    }
}
